package com.cardone.common.io;

import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.cardone.context.action.Run1Action;
import lombok.Setter;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.*;

import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * Created by Administrator on 2014/12/3.
 */
public class FtpManager extends AbstractFsManager implements FsManager {
    @Setter
    private String hostname;

    @Setter
    private String user;

    @Setter
    private String password;

    @Setter
    private int port = 21;

    /**
     * 键前缀名称
     */
    private String keyPrefix = "entityFile/";

    public FtpManager() {
        super();
    }

    private String newKey(String key) {
        if (StringUtils.isBlank(keyPrefix)) {
            return key;
        }

        return keyPrefix + key;
    }

    @Override
    public void saveFile(InputStream inputStream, long size, String filename, String contentType) throws IOException {
        String newKey = this.newKey(filename);

        this.run(ftpclient -> {
            try {
                ftpclient.storeFile(newKey, inputStream);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    private void run(Run1Action<FTPClient> runAction) throws IOException {
        FTPClient ftpClient = null;

        try {
            ftpClient = new FTPClient();

            //设置服务器名和端口
            ftpClient.connect(hostname, port);

            int reply = ftpClient.getReplyCode();

            if (!FTPReply.isPositiveCompletion(reply)) {
                //连接错误的时候报错。
                throw new IOException("Can't Connect to :" + hostname);
            }

            //登录
            if (ftpClient.login(user, password) == false) {
                throw new IOException("Invalid user/password");
            }

            //设置传送文件模式
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            runAction.run(ftpClient);
        } catch (IOException e) {
            throw e;
        } finally {
            if (ftpClient != null) {
                if (ftpClient.isConnected()) {
                    ftpClient.disconnect(); //解除连接
                }
            }
        }
    }

    @Override
    public void writeTo(OutputStream toOutputStream, String filename) throws IOException {
        String newKey = this.newKey(filename);

        this.run(ftpclient -> {
            try {
                ftpclient.retrieveFile(newKey, toOutputStream);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    @Override
    public void saveFile(InputStream inputStream, long size, String filename) throws IOException {
        saveFile(inputStream, size, filename, null);
    }

    @Override
    public void writeTo(HttpServletResponse response, String filename) throws IOException {
        String newKey = this.newKey(filename);

        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");

        final String fileExtension = FilenameUtils.getExtension(filename);

        for (final String writeToKey : writeToMap.keySet()) {
            if (StringUtils.containsIgnoreCase(writeToKey, fileExtension)) {
                writeToMap.get(writeToKey).run(response, filename);

                try (OutputStream out = response.getOutputStream()) {
                    this.run(ftpclient -> {
                        try {
                            ftpclient.retrieveFile(newKey, out);
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    });

                    out.flush();

                    response.flushBuffer();
                }

                return;
            }
        }

        try (OutputStream out = response.getOutputStream()) {
            this.run(ftpclient -> {
                try {
                    ftpclient.retrieveFile(newKey, out);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });

            out.flush();

            response.flushBuffer();
        }
    }

    @Override
    public void writeTo(String toFilename, String filename) throws IOException {
        writeTo(new File(toFilename), filename);
    }

    @Override
    public void writeTo(File toFile, String filename) throws IOException {
        String newKey = this.newKey(filename);

       try( FileOutputStream outStream = new FileOutputStream(toFile)){
           this.run(ftpclient -> {
               try {
                   ftpclient.retrieveFile(newKey, outStream);
               } catch (Exception e) {
                   throw new RuntimeException(e);
               }
           });
       }
    }
}
